﻿using System;
using System.Collections.Generic;

namespace DataProcess.Mathematics
{
    /// <summary>
    /// 检验是否为数字，数字进制转换
    /// </summary>
    public sealed class NumberCase
    {
        static void validCheck(int basenumber)
        {
            if (basenumber != 2 && basenumber != 8 && basenumber != 10 && basenumber != 16)
                throw new InvalidOperationException("转化进制仅支持2，8，10，16");
        }
        /// <summary>
        /// 转化为指定进制
        /// </summary>
        /// <param name="num"></param>
        /// <param name="to">指定的进制，有效值：2,8,10,16</param>
        /// <returns></returns>
        public static string ExchangeFromTen(long num, int to, int? resultlength = null)
        {
            validCheck(to);
            string res = Convert.ToString(num, to);
            return resultlength == null ? res : res.PadLeft((int)resultlength);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="num"></param>
        /// <param name="to"></param>
        /// <param name="resultlength"></param>
        /// <returns></returns>
        public static string ExchangeFromTen(int num, int to, int? resultlength = null)
        {
            validCheck(to);
            string res = Convert.ToString(num, to);
            return resultlength == null ? res : res.PadLeft((int)resultlength);
        }
        /// <summary>
        /// 将指定进制的字符串转化为10进制正整数
        /// </summary>
        /// <param name="num">指定的数字</param>
        /// <param name="from">指定的进制，有效值：2,8,10,16</param>
        /// <returns></returns>
        public static ulong ExchangeToTen(string num, int from)
        {
            validCheck(from);
            return Convert.ToUInt64(num, from);
        }
        /// <summary>
        /// 是否是数字
        /// </summary>
        /// <param name="text"></param>
        /// <param name="isInt">是否为整数</param>
        /// <returns></returns>
        public static bool IsNumbers(string text, bool isInt = true)
        {
            switch (isInt)
            {
                case true:
                    int p = 0;
                    return int.TryParse(text, out p);
                default:
                    double d = 0;
                    return double.TryParse(text, out d);
            }
        }
    }
    /// <summary>
    /// 到达数字上限会自动重回数字下限，形成数字循环
    /// </summary>
    public class LoopNumber
    {
        #region 运算符重载
        public static implicit operator int(LoopNumber loop)
        {
            return loop.number;
        }
        public static LoopNumber operator +(LoopNumber a, LoopNumber b)
        {
            LoopNumber num = new LoopNumber(a.min, a.max)
            {
                Number = a.Number + b.Number
            };
            return num;
        }
        public static LoopNumber operator +(LoopNumber a, int x)
        {
            LoopNumber number = new LoopNumber(a.min, a.max)
            {
                Number = a.Number + x
            };
            return number;
        }
        public static LoopNumber operator -(LoopNumber a, LoopNumber b)
        {
            LoopNumber num = new LoopNumber(a.min, a.max)
            {
                Number = a.Number - b.Number
            };
            return num;
        }
        public static LoopNumber operator -(LoopNumber a, int x)
        {
            LoopNumber number = new LoopNumber(a.min, a.max)
            {
                Number = a.Number - x
            };
            return number;
        }
        public static LoopNumber operator ++(LoopNumber a)
        {
            a.Number += 1;
            return a;
        }
        public static LoopNumber operator --(LoopNumber a)
        {
            a.Number -= 1;
            return a;
        }
        public static bool operator ==(LoopNumber a, int x)
        {
            return a.Number == x;
        }
        public static bool operator !=(LoopNumber a, int x)
        {
            return a.Number != x;
        }
        public static bool operator >(LoopNumber a, int x)
        {
            return a.Number > x;
        }
        public static bool operator <(LoopNumber a, int x)
        {
            return a.Number < x;
        }
        public static bool operator >=(LoopNumber a, int x)
        {
            return a.Number >= x;
        }
        public static bool operator <=(LoopNumber a, int x)
        {
            return a.Number <= x;
        }
        public static bool operator ==(LoopNumber a, LoopNumber b)
        {
            return a.Number == b.Number;
        }
        public static bool operator !=(LoopNumber a, LoopNumber b)
        {
            return a.Number != b.Number;
        }
        public static bool operator >(LoopNumber a, LoopNumber b)
        {
            return a.Number > b.Number;
        }
        public static bool operator <(LoopNumber a, LoopNumber b)
        {
            return a.Number < b.Number;
        }
        public static bool operator >=(LoopNumber a, LoopNumber b)
        {
            return a.Number >= b.Number;
        }
        public static bool operator <=(LoopNumber a, LoopNumber b)
        {
            return a.Number <= b.Number;
        }
        #endregion
        public override string ToString()
        {
            return number.ToString();
        }
        /// <summary>
        /// 验证另一个LoopNumber是否完全与自身相同，若仅需要对比值，请用==
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            LoopNumber loop = (LoopNumber)obj;
            return loop.max == max && loop.min == min && loop.Number == Number;
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="num">初始值，</param>
        /// <param name="start">数字下限(默认为int最小值)</param>
        /// <param name="end">数字上限(默认为int最大值)</param>
        public LoopNumber(int num = 0, int start = int.MinValue, int end = int.MaxValue)
        {

            min = start;
            max = end;
            Number = num;
            if (min.Equals(max))
            {
                throw new Exception("循环尾数不能是循环起始数");
            }
        }
        public static LoopNumber Parse(int num, int start, int end)
        {
            return new LoopNumber(num, start, end);
        }
        /// <summary>
        /// 循环数的最大数
        /// </summary>
        public int Max
        {
            get => max;
            set => max = value;
        }
        /// <summary>
        ///循环数的最小数
        /// </summary>
        public int Min
        {
            get => min;
            set => min = value;
        }
        private int max, min;
        private int number = 0;
        /// <summary>
        /// 循环的数字
        /// </summary>
        public int Number
        {
            get => number;
            set
            {
                if (value > max)
                {
                    number = min;
                }
                else if (value < min)
                {
                    number = max;
                }
                else
                {
                    number = value;
                }
            }
        }
    }
    /// <summary>
    /// 细节浮点数
    /// </summary>
    public class DetailDouble
    {
        private double num;
        private int ac = 5;
        private bool isreverse;
        private DetailInterger before, after;


        /// <summary>
        /// 是否反转，True：最靠近小数点处开始，False则反之
        /// </summary>
        public bool IsReverse
        {
            get => isreverse;
            set
            {
                if (value != isreverse)
                {
                    isreverse = value;
                    before = getBefore();
                    after = getAfter();
                }

            }
        }
        public int Length => before.Length;


        /// <summary>
        /// 设置整数部分长度
        /// </summary>
        /// <param name="l"></param>
        public void ExpandLength(int l)
        {
            before.ExpandLength(l);
        }

        /// <summary>
        /// 原始数字
        /// </summary>
        public double OrginNumber
        {
            get => num;
            set
            {
                num = value;
                ComfirmType();
                before = getBefore();
                after = getAfter();
            }
        }
        /// <summary>
        /// 获取小数点前后指定位数的数字
        /// </summary>
        /// <param name="position">小数点前后</param>
        /// <param name="index">位置序号</param>
        /// <returns></returns>
        public int this[NumberPosition position, int index]
        {
            get
            {
                if (position == NumberPosition.小数点前)
                {
                    return before[index];
                }
                else
                {
                    return after[index];
                }
            }
            set
            {
                if (position == NumberPosition.小数点前)
                {
                    before[index] = value;
                }
                else
                {
                    after[index] = value;
                }
                num = double.Parse(ToString());
            }

        }

        private DetailInterger getBefore()
        {
            int t = (int)num;
            return new DetailInterger(t, IsReverse);
        }

        private DetailInterger getAfter()
        {
            string t;
            if (num - getBefore() == 0)
            {
                t = "0";
            }
            else
            {
                t = num.ToString().Split('.')[1];
            }

            if (t.Length >= ac)
            {
                t = t.Substring(0, ac);
            }
            else
            {
                t = t.PadRight(ac, '0');
            }
            DetailInterger res = new DetailInterger(int.Parse(t), !IsReverse);
            res.ExpandLength(ac);
            return res;
        }

        private void ComfirmType()
        {
            if (num < 0)
            {
                Type = NumberType.负数;
            }
            else
            {
                Type = NumberType.正数;
            }
        }
        public NumberType Type
        {
            get;
            private set;
        }
        /// <summary>
        /// 小数点后精度，不会采取四舍五入
        /// </summary>
        public int Accuracy
        {
            get => ac;
            set
            {
                ac = value;
                after = getAfter();
            }
        }

        public DetailDouble(double num, bool isreverse = true)
        {
            this.isreverse = isreverse;
            OrginNumber = num;
        }
        public override string ToString()
        {
            return before.ToString() + "." + after.ToString();
        }

    }

    public enum NumberPosition
    {
        小数点前, 小数点后
    }

    /// <summary>
    /// 详细整数的类型
    /// </summary>
    public enum NumberType
    {
        正数, 负数
    }

    /// <summary>
    /// 详细整数，可拆出数字的每位数
    /// </summary>
    public class DetailInterger
    {
        private int num;
        private int length;
        private string arr;

        public NumberType Type
        {
            get;
            private set;
        }

        /// <summary>
        /// 原始数字
        /// </summary>
        public int OrginNumber
        {
            get => num;
            set
            {
                num = value;
                ComfirmType();
                getLength();
                arr = num.ToString();
                arr = arr.Trim('-');
                ExpandLength(length);
                IsReverse = isreverse;

            }
        }
        /// <summary>
        /// 拓展长度
        /// </summary>
        /// <param name="l">需要拓展的长度，必须比当前长度长</param>
        public void ExpandLength(int l)
        {
            if (length <= l)
            {
                if (IsReverse)
                {
                    arr = arr.PadRight(l, '0');
                }
                else
                {
                    arr = arr.PadRight(l, '0');
                }

                length = l;
            }
            else
            {
                throw new Exception("无法拓展位数至比当前位数短");
            }
        }

        private void ComfirmType()
        {
            if (num < 0)
            {
                Type = NumberType.负数;
            }
            else
            {
                Type = NumberType.正数;
            }
        }

        /// <summary>
        /// 数字位数
        /// </summary>
        public int Length => length;

        private bool isreverse = true;
        /// <summary>
        /// 是否位数反转，True：从个位开始，False：从最高位开始
        /// </summary>
        public bool IsReverse
        {
            get => isreverse;
            set
            {
                isreverse = value;

                int tmp = num;

                if (Type == NumberType.负数)
                {
                    tmp = -num;
                }

                List<char> a = new List<char>(arr.ToCharArray());
                if (IsReverse)
                {
                    a.Reverse();
                }
                arr = new string(a.ToArray());
                arr = arr.Trim('-');
            }
        }

        private void getLength()
        {
            length = num.ToString().Length;
            if (Type == NumberType.负数)
            {
                length--;
            }
        }
        /// <summary>
        /// 指定位上的数字
        /// </summary>
        /// <param name="index">指定位数</param>
        /// <returns></returns>
        public int this[int index]
        {
            get
            {
                if (index >= arr.Length)
                {
                    throw new Exception("超出位数");
                }
                return int.Parse(arr[index].ToString());
            }
            set
            {
                if (value > 9 || value < 0)
                {
                    throw new Exception("每一位上仅能为个位数");
                }

                if (index >= arr.Length)
                {
                    throw new Exception("超出位数");
                }
                char[] c = arr.ToCharArray();
                c[index] = value.ToString()[0];
                arr = new string(c);
                num = arrToInt();
            }
        }

        private int arrToInt()
        {
            return int.Parse(ToString());
        }
        public override string ToString()
        {
            if (Type == NumberType.负数)
            {
                return "-" + arr;
            }

            if (IsReverse)
            {
                List<char> a = new List<char>(arr.ToCharArray());
                a.Reverse();
                arr = new string(a.ToArray());
            }
            return arr;
        }

        public override bool Equals(object obj)
        {
            return obj.ToString().Equals(ToString());
        }
        public DetailInterger(int item, bool isreverse = true)
        {
            this.isreverse = isreverse;
            OrginNumber = item;

        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }


        public static implicit operator int(DetailInterger item)
        {
            return item.num;
        }

        public static explicit operator DetailInterger(int item)
        {
            return new DetailInterger(item);
        }
    }
}
